package rdb

import (
	"context"
	"fmt"
	"sync"

	"github.com/redis/go-redis/v9"
)

type Set interface {
	TopicKey() string
	RedisClient() *redis.Client
	IsExist(key string) (bool, error)
	Add(key string) error
	Adds(keys []string) error
	Del(key string) error
	Dels(keys []string) error
	Spop(limit uint) ([]string, error)
	SpopOne() (string, error)
	SpopAll() ([]string, error)
	GetRandKeys(limit uint) ([]string, error)
	Count() (int64, error)
	GetAllKey() ([]string, error)
	ClearAll() error
}

type _set struct {
	Topic string        //主题
	Redis *redis.Client //Redis客户端
	RWL   sync.RWMutex  //读写锁
}

func NewSet(client *redis.Client, topic string) Set {
	return &_set{
		Topic: topic,
		Redis: client,
		RWL:   sync.RWMutex{},
	}
}

// TopicKey 返回默认生成的主题key
func (s *_set) TopicKey() string {
	return fmt.Sprint("Set_", s.Topic)
}

// RedisClient 返回绑定的Redis客户端
func (s *_set) RedisClient() *redis.Client {
	return s.Redis
}

// IsExist 是否存在
func (s *_set) IsExist(key string) (bool, error) {
	s.RWL.RLock()
	result, err := s.Redis.SIsMember(context.Background(), s.TopicKey(), key).Result()
	s.RWL.RUnlock()
	return result, err
}

// Add 添加一个key
func (s *_set) Add(key string) error {
	s.RWL.Lock()
	err := s.Redis.SAdd(context.Background(), s.TopicKey(), key).Err()
	s.RWL.Unlock()
	return err
}

// Adds 添加多个key
func (s *_set) Adds(keys []string) error {
	s.RWL.Lock()
	var temp []any
	for _, d := range keys {
		temp = append(temp, d)
	}
	err := s.Redis.SAdd(context.Background(), s.TopicKey(), temp...).Err()
	s.RWL.Unlock()
	return err
}

// Del 删除指定的key
func (s *_set) Del(key string) error {
	s.RWL.Lock()
	err := s.Redis.SRem(context.Background(), s.TopicKey(), key).Err()
	s.RWL.Unlock()
	return err
}

// Dels 删除指定的keys
func (s *_set) Dels(keys []string) error {
	s.RWL.Lock()
	var temp []any
	for _, d := range keys {
		temp = append(temp, d)
	}
	err := s.Redis.SRem(context.Background(), s.TopicKey(), temp...).Err()
	s.RWL.Unlock()
	return err
}

// Spop 获取并删除limit个key
func (s *_set) Spop(limit uint) ([]string, error) {
	s.RWL.Lock()
	result, err := s.Redis.SPopN(context.Background(), s.TopicKey(), int64(limit)).Result()
	s.RWL.Unlock()
	return result, err
}

// SpopOne 获取并删除 1 个key
func (s *_set) SpopOne() (string, error) {
	s.RWL.Lock()
	result, err := s.Redis.SPop(context.Background(), s.TopicKey()).Result()
	s.RWL.Unlock()
	return result, err
}

// SpopAll 获取并删除limit个key
func (s *_set) SpopAll() ([]string, error) {
	s.RWL.Lock()
	//1、获取所有成员列表
	result, err := s.Redis.SMembers(context.Background(), s.TopicKey()).Result()
	if err == nil {
		//2、获取成员列表成功后，直接删除键
		err = s.Redis.Del(context.Background(), s.TopicKey()).Err()
	}
	s.RWL.Unlock()
	return result, err
}

// GetRandKeys 随机获取limit个key
func (s *_set) GetRandKeys(limit uint) ([]string, error) {
	s.RWL.RLock()
	result, err := s.Redis.SRandMemberN(context.Background(), s.TopicKey(), int64(limit)).Result()
	s.RWL.RUnlock()
	return result, err
}

// Count 获取集合的成员数量
func (s *_set) Count() (int64, error) {
	s.RWL.RLock()
	defer s.RWL.RUnlock()
	result, err := s.Redis.SCard(context.Background(), s.TopicKey()).Result()
	if err == nil || err == redis.Nil {
		return result, nil
	}
	return result, err
}

// GetAllKey 获取所有的key
func (s *_set) GetAllKey() ([]string, error) {
	s.RWL.RLock()
	result, err := s.Redis.SMembers(context.Background(), s.TopicKey()).Result()
	s.RWL.RUnlock()
	return result, err
}

// ClearAll 清空所有的记录（直接删除key）
func (s *_set) ClearAll() error {
	s.RWL.Lock()
	err := s.Redis.Del(context.Background(), s.TopicKey()).Err()
	s.RWL.Unlock()
	return err
}
